/* 
 * File:   RTS.cpp
 * Author: James
 * 
 * Created on November 7, 2010, 7:35 PM
 */

#include "RTS.h"



RTS::RTS(Process* procs, int n) {
    // init important local class vars
    nProcs = n;
    processes = procs;
    clock = Clock();
    IOQueue = priority_queue<Process, vector<Process>, CompareIOCompletion>();
    SDF_queue = priority_queue<Process, vector<Process>, CompareDeadline>();

}

RTS::~RTS() {

    

}

void RTS::run() {

    // index for traversing processes in arrival order
    
    
    procIndex = 0;
    Process p;
    int ganttSlice[3];
    int pStart = 0; // starting time of the current process for gantt info

    
    bool running = true;
    while (running) {


        scheduleProcesses();

        // if preemptive, set curProcess to be top of the list

        //

        if (curProcess != NULL) {
            p = *curProcess;
            // run the process 1 ms
            --p;

            // check if it has IO now
            if ((p.getIO() > 0) && (p.getRemaining() == 2)) {

                // set its IO completion time
                p.setIOCompletion(clock.getTime()+p.getIO());
                // then add it to the priority queue.
                IOQueue.push(p);

                // now remove this item
                SDF_queue.pop();

                /* TODO */
                // set and send gantt slice to stats

                // increment turnaround of stats
                
                if (!SDF_queue.empty()) {
                    
                    // set the start time of the next proc
                    pStart = clock.getTime();
                    // switch the running process to the next highest priority
                    p = SDF_queue.top();
                    curProcess = &p;
                }

            } else if (p.isDone()) {
                // take it off of the queue
                SDF_queue.pop();


                /* TODO */
                // set and send gantt slice to stats

                // increment turnaround of stats


                if (SDF_queue.empty()) {
                    // if there's nothing to run, cpu spins
                    curProcess = NULL;
                } else {
                    // set the start time of the next proc
                    pStart = clock.getTime();
                    p = SDF_queue.top();
                    curProcess = &p;
                }
            } else {
                // is it behind schedule?
                if (p.getDeadline() > clock.getTime()) {
                    cout << "Proc" << p.getID() << " is late." << endl;
                    
                    // if hard rts, kill this proc

                        /* TODO */
                        // set and send gantt slice to stats

                        // increment turnaround of stats

                    //
                }
            }
        } else { // cur process is NULL
            // processor isn't running & all processes have been consumed
            if (procIndex >= nProcs) {
                running = false;// exit
            } else {
                // if the queue has something, grab it
                if (!SDF_queue.empty()) {

                    

                    // set the start time of the next proc
                    pStart = clock.getTime();
                    p = SDF_queue.top();
                    curProcess = &p;
                    
                }
            }
        }



        // increment clock timer
        ++clock;

    }


}

void RTS::scheduleProcesses() {

    bool done = false;

    while (!done) {

        // if arrival is bad (negative, letter, ect - skip)
        if (processes[procIndex].getArrive() < clock.getTime()) {
            procIndex++;
        } else if (processes[procIndex].getArrive() == clock.getTime()) {
            // the process arrives now
            SDF_queue.push(processes[procIndex]);
            procIndex++;
        } else if (processes[procIndex].getArrive() > clock.getTime()) {
            done = true;
        }
    }
}
